﻿using System.Collections.Immutable;
using System.Linq;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.Diagnostics;
using UIOC.CodeAnalysis.Diagnostics;
using UIOC.CodeAnalysis.Extensions;

namespace UIOC.CodeAnalysis.Analyzers;

[DiagnosticAnalyzer(LanguageNames.CSharp)]
internal sealed class AutowiredAttributeReadOnlyAnalyzer : DiagnosticAnalyzer {

    public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics
        => ImmutableArray.Create(AutowiredAttributeReadOnlyDiagnostic.Rule);

    public override void Initialize(AnalysisContext context) {
        context.EnableConcurrentExecution();
        context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
        // 注册所有所有赋值运算符（包括简单赋值和复合赋值）
        context.RegisterSyntaxNodeAction(AnalyzeAssignment,
            // 简单赋值：=
            SyntaxKind.SimpleAssignmentExpression,
            // 算术复合赋值：+=, -=, *=, /=, %=
            SyntaxKind.AddAssignmentExpression,
            SyntaxKind.SubtractAssignmentExpression,
            SyntaxKind.MultiplyAssignmentExpression,
            SyntaxKind.DivideAssignmentExpression,
            SyntaxKind.ModuloAssignmentExpression,
            // 位运算复合赋值：&=, |=, ^=, <<=, >>=
            SyntaxKind.AndAssignmentExpression,
            SyntaxKind.OrAssignmentExpression,
            SyntaxKind.ExclusiveOrAssignmentExpression,
            SyntaxKind.LeftShiftAssignmentExpression,
            SyntaxKind.RightShiftAssignmentExpression);
    }

    /// <summary>
    /// 分析成员访问表达式（如 obj.fieldName）
    /// </summary>
    private void AnalyzeAssignment(SyntaxNodeAnalysisContext context) {
        var compilation = context.Compilation;
        var assembly = compilation.Assembly;
        if (assembly.IsIgnore()) {
            return;
        }

        // 转换为赋值表达式语法节点
        if (context.Node is not AssignmentExpressionSyntax assignmentExpressionSyntax) {
            return;
        }

        // 提取赋值的左侧（被赋值的目标）
        var leftExpressionSyntax = assignmentExpressionSyntax.Left;

        if (leftExpressionSyntax is MemberAccessExpressionSyntax memberAccess) { // 场景1：左侧是成员访问（如 obj.field = ... 或 this.field += ...）
            AnalyzeMemberAccessAssignment(memberAccess, context);
        } else if (leftExpressionSyntax is IdentifierNameSyntax identifier) { // 场景2：左侧是标识符（如 field = ... 或 field *= ...）
            AnalyzeIdentifierAssignment(identifier, context);
        }
    }

    /// <summary>
    /// 分析成员访问形式的赋值（如 obj.field = ... 或 this.field += ...）
    /// </summary>
    private void AnalyzeMemberAccessAssignment(MemberAccessExpressionSyntax memberAccess, SyntaxNodeAnalysisContext context) {
        var memberSymbol = context.SemanticModel.GetSymbolInfo(memberAccess).Symbol;
        if (memberSymbol is not IFieldSymbol fieldSymbol)
            return;

        if (IsTargetField(fieldSymbol, context)) {
            context.ReportDiagnostic(Diagnostic.Create(
                AutowiredAttributeReadOnlyDiagnostic.Rule,
                memberAccess.Name.GetLocation(),
                fieldSymbol.Name,
                GetAttributeSourceText(fieldSymbol, context)
            ));
        }
    }

    /// <summary>
    /// 分析标识符形式的赋值（如 field = ... 或 field *= ...）
    /// </summary>
    private void AnalyzeIdentifierAssignment(IdentifierNameSyntax identifier, SyntaxNodeAnalysisContext context) {
        // 排除字段声明中的赋值（如 public int field = 0; 中的初始化）
        if (IsPartOfFieldDeclaration(identifier))
            return;

        // 获取被赋值的字段符号
        var symbol = context.SemanticModel.GetSymbolInfo(identifier).Symbol;
        if (symbol is not IFieldSymbol fieldSymbol)
            return;

        // 检查是否为目标字段
        if (IsTargetField(fieldSymbol, context)) {
            // 报错位置：标识符
            context.ReportDiagnostic(Diagnostic.Create(
                AutowiredAttributeReadOnlyDiagnostic.Rule,
                identifier.GetLocation(),
                fieldSymbol.Name,
                GetAttributeSourceText(fieldSymbol, context)
            ));
        }
    }

    /// <summary>
    /// 检查字段是否标记了[Autowired]
    /// </summary>
    private bool IsTargetField(IFieldSymbol fieldSymbol, SyntaxNodeAnalysisContext context) {
        var compilation = context.SemanticModel.Compilation;
        var autowiredAttributeSymbol = compilation.GetTypeByMetadataName(AttributeFullNames.Autowired);
        if (autowiredAttributeSymbol == null) {
            return false;
        }
        return fieldSymbol.GetAttributes(autowiredAttributeSymbol).Any();
    }

    /// <summary>
    /// 判断标识符是否属于字段声明（避免检测声明语句本身）
    /// </summary>
    private bool IsPartOfFieldDeclaration(IdentifierNameSyntax identifier) {
        return identifier.Ancestors().Any(n => n is FieldDeclarationSyntax);
    }

    /// <summary>
    /// 获取字段上标记的特性原始文本
    /// </summary>
    private string GetAttributeSourceText(IFieldSymbol fieldSymbol, SyntaxNodeAnalysisContext context) {
        var compilation = context.SemanticModel.Compilation;
        // 获取目标特性符号
        var autowiredAttributeSymbol = compilation.GetTypeByMetadataName(AttributeFullNames.Autowired);
        if (autowiredAttributeSymbol == null) {
            return null;
        }

        // 查找字段上的目标特性
        var attributeData = fieldSymbol.GetAttributes(autowiredAttributeSymbol).FirstOrDefault();
        if (attributeData == null) {
            return null;
        }

        try {
            var syntaxRef = attributeData.ApplicationSyntaxReference;
            var syntax = syntaxRef?.GetSyntax() as AttributeSyntax;
            return syntax?.ToFullString().Trim();
        } catch {
            return null;
        }
    }
}
